﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using Microsoft.Surface.Presentation.Controls;
using Microsoft.Surface.Presentation.Input;
using ScrumTable.UI.View.Command;
using ScrumTable.UI.View.Controls;
using ScrumTable.UI.View.WinTouch.Util;
using ScrumTable.UI.ViewModel;

namespace ScrumTable.UI.View.WinTouch.UserControls.PlanningPoker
{
    /// <summary>
	/// Interaction logic for SearchScreen.xaml
	/// </summary>
	public partial class PlanningPoker : IDropUserControl
	{
	  


        #region Decleration
        //--------------------------------------------------------------------
        // Decleration
        //--------------------------------------------------------------------

        private const long ScrumPokerCardTagSeries = 0;
        private readonly ObservableCollection<ScrumPokerCard> _placedCards = new ObservableCollection<ScrumPokerCard>();
        
        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------



        public ObservableCollection<ScrumPokerCard> PlacedCards
        {
            get
            {
                FillItems();
                return _placedCards;
            }
        }


        public bool IsSurfaceMode { get; set; }

        public ObservableCollection<ScrumPokerCard>  AllCards
        {
            get { return ScrumPokerCard.CreateCardsForDomain(); }
        }

      

      
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        public PlanningPoker()
        {
            _placedCards.CollectionChanged += (a, b) => { ExposeButton.IsEnabled = _placedCards.Count(x => !x.IsDummyCard && x.IsHidden) > 0; };
            _placedCards.CollectionChanged += (a, b) => { ReplayButton.IsEnabled = _placedCards.Count(x => !x.IsHidden && !x.IsDummyCard) > 0; };
            
            IsSurfaceMode = SurfaceUtil.IsSurfaceRunning();
            InitializeComponent();
            if (!IsSurfaceMode)
            {
                ScrumPokerCardsContainer.Margin = new Thickness(0, 20, 0, 0);
            }
            Maingrid.Margin = new Thickness(-(ConfigManager.Config.ControlSize.X * 2 + 75 * 2 + 30),0,0,0);
            CardTagVisualizer.TouchEnter += OnContactEnter;
            CardTagVisualizer.TouchLeave += OnContactLeave;
            CardTagVisualizer.VisualizationInitialized += OnCardVisualizationInitialized;
            Loaded += OnLoaded;
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        private void AddTagDef(long value)
        {
            var def = CardTagVisualizer.Definitions.FirstOrDefault(x => x.Value == value);
            if( def != null) { return; }

            const string target = @"UserControls\PlanningPoker\ScrumPokerCardTag.xaml";
            var tagDef = new TagVisualizationDefinition();
            tagDef.Series = ScrumPokerCardTagSeries;
            // The tag value that this definition will respond to.
            tagDef.Value = value;
            // The .xaml file for the UI
            tagDef.Source = new Uri(target, UriKind.Relative);
            // The maximum number for this tag value.
            tagDef.MaxCount = 1;
            // The visualization stays for 1 second.
            tagDef.LostTagTimeout = 1000.0;
            // Orientation offset (default).
            tagDef.OrientationOffsetFromTag = 90.0;
            // Physical offset (horizontal inches, vertical inches).
            tagDef.PhysicalCenterOffsetFromTag = new Vector(0, 0);
            // Tag removal behavior (default).
            tagDef.TagRemovedBehavior = TagRemovedBehavior.Fade;
            // Orient UI to tag? (default).
            tagDef.UsesTagOrientation = true;
            // Add the definition to the collection.
            CardTagVisualizer.Definitions.Add(tagDef);
        }

        private void FillItems(bool deleteDummies = false)
        {
            if(deleteDummies)
            {
                for (int i = PlacedCards.Count - 1; i >= 0; --i)
                {
                    if (!PlacedCards[i].IsDummyCard)
                    {
                        PlacedCards.RemoveAt(i);
                    }
                }
            }
            while (_placedCards.Count < 8)
            {
                _placedCards.Add(new ScrumPokerCard { IsDummyCard = true });
            }
        }


        private void ShowCardSelection()
        {
            ScrumPokerCardsContainer.Visibility = Visibility.Visible;
            ((Storyboard)Resources["StoryboardShowOtherCards"]).Begin();
        }

    

        private void HideCardSelection(bool showAnimation=false)
        {
            if (showAnimation)
            {
                var storyboard = ((Storyboard) Resources["StoryboardHideOtherCards"]);
                 storyboard.Begin();
            }
            else
            {
                ScrumPokerCardsContainer.Visibility = Visibility.Collapsed;
            }
        }

        private void ClosePoker()
        {
            var storyboard = ((Storyboard)Resources["StoryboardQuit"]);
            HideCardSelection();
            storyboard.Completed += (a, b) => ((AppScreen)Application.Current.MainWindow).RemoveItem(this);
            storyboard.Begin();
        }


        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------



        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            if (!IsSurfaceMode)
            {
                column0.Width = new GridLength(95, GridUnitType.Pixel);
                Maingrid.Margin = new Thickness(0);
                ShowCardSelection();
            }
            else
            {
                ((Storyboard)Resources["StoryboardLoaded"]).Begin();
            }
        }


        private void OnCardVisualizationInitialized(object sender, TagVisualizerEventArgs e)
        {
            if (e != null && e.TagVisualization != null)
            {
                ScrumPokerCard card = ScrumPokerCard.CreateForByteTagvalue(e.TagVisualization.VisualizedTag.Value);
                if (e.TagVisualization is ScrumPokerCardTag)
                {
                    var tag = (ScrumPokerCardTag)e.TagVisualization;

                    tag.CardBorder.BorderBrush = card.Color;
                    tag.CardBorder.Background = card.Color;
                    var blurEffect = new BlurEffect { Radius = 10 };
                    tag.CardBorder.Effect = blurEffect;
                }
            }
        }

        private void OnContactEnter(object sender, TouchEventArgs e)
        {
            
            if (e.TouchDevice.GetIsTagRecognized())
            {
                var data = e.TouchDevice.GetTagData();
                if (data.Series == ScrumPokerCardTagSeries)
                {
                    long value = data.Value;
                    AddTagDef(value);

                    ScrumPokerCard card = ScrumPokerCard.CreateForByteTagvalue(value);
                    if (!PlacedCards.Contains(card))
                    {
                        card.IsHidden = true;
                        card.Count = 1;

                        var dummyItem = PlacedCards.FirstOrDefault(x => x.IsDummyCard);
                        if (dummyItem != null)
                        {
                            var dummyIndex = PlacedCards.IndexOf(dummyItem);
                            PlacedCards.Insert(dummyIndex, card);
                            PlacedCards.RemoveAt(dummyIndex+1);
                        }
                        else
                        {
                            PlacedCards.Add((card));    
                        }
                    }
                    else
                    {
                        PlacedCards.First(x => x.IdentityTagValue == card.IdentityTagValue).Count += 1;
                    }
                }
            }
        }

        private void OnContactLeave(object sender, TouchEventArgs e)
        {

            if (e.TouchDevice.GetIsTagRecognized())
            {
                var data = e.TouchDevice.GetTagData();
                if (data.Series == ScrumPokerCardTagSeries)
                {
                    long value = data.Value;
                    AddTagDef(value);
                    var placedCard = PlacedCards.FirstOrDefault(x => x.IdentityTagValue == value);
                    if (placedCard != null)
                    {
                        placedCard.Count -= 1;
                        //do not remove if the the card is exposed (only remove with replay)
                        if (placedCard.Count <= 0 && placedCard.IsHidden)
                        {
                            PlacedCards.Remove((placedCard));
                            FillItems();
                        }
                    }
                }
            }
        }

        private void OnExpose(object sender, RoutedEventArgs e)
        {
            foreach(var x in PlacedCards)
            {
                x.IsHidden = false;
            }

            int numberCards = PlacedCards.Count(card2 => !card2.IsDummyCard);
            if (numberCards > 0)
            {
                double average = PlacedCards.Sum(x => x.Number) / numberCards;
                var card1 = AllCards.First(x=> x.Number >= average);
                var card2 = AllCards.Last(x => x.Number <= average);
                AverageCard.DataContext = Math.Abs(card1.Number - average) > Math.Abs(card2.Number - average) ? card2 : card1;
            }
            else
            {
                AverageCard.DataContext = null;
            }
            AverageCard.Visibility = Visibility.Visible;
            ReplayButton.IsEnabled = true;
            ExposeButton.IsEnabled = false;
            ShowCardSelection();
        }

        private void OnReplay(object sender, RoutedEventArgs e)
        {
            HideCardSelection(true);
            AverageCard.Visibility = Visibility.Hidden;
            FillItems(true);
        }

        private void OnPlayedCardListClicked(object sender, SelectionChangedEventArgs e)
        {
            OnExpose(sender, e);
        }


        private void OnClose(object sender, RoutedEventArgs e)
        {
            ClosePoker();
        }

        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            e.Handled = SetUserStoryPoint(((SurfaceDragDropListBox) sender).SelectedItem as ScrumPokerCard);
        }

        private bool SetUserStoryPoint(ScrumPokerCard card)
        {
            if (card != null && !card.IsHidden && !card.IsDummyCard)
            {
                if (DataContext is UserStoryViewModel)
                {
                    ((UserStoryViewModel)DataContext).StoryPoints = card.Number;
                }
                else
                {
                    CommandLib.SelectStoryPoint.Execute(card, this);
                }
                ClosePoker();
                return true;
            }
            return false;
        }
	    #endregion

        #region Implementation of IDropUserControl

        public FrameworkElement GetRootControl
        {
            get { return RootDummy; }
        }

        public bool ShowIconWithbackground
        {
            get { return false; }
        }

        public CanDropResult CanDrop(object objectToDrop)
        {
            return CanDropResult.None;
        }


        private void OnAverageClick(object sender, MouseButtonEventArgs e)
        {
            SetUserStoryPoint(AverageCard.DataContext as ScrumPokerCard);
        }

        private void OnAverageClick(object sender, TouchEventArgs e)
        {
            SetUserStoryPoint(AverageCard.DataContext as ScrumPokerCard);
        }

        #endregion

     
	}
}